package com.vvv.shortlink.gateway.filter;

import com.alibaba.fastjson2.JSON;
import com.vvv.shortlink.gateway.dto.GatewayErrorResult;
import com.vvv.shortlink.gateway.properties.GateWayWhitePathListProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Map;

/**
 * @author vvv
 * @date 2024/2/29 18 25
 * discription
 */
@Order(10)
@Component
@EnableConfigurationProperties(GateWayWhitePathListProperties.class)
@RequiredArgsConstructor
public class AuthorizeFilter implements GlobalFilter {

    private final GateWayWhitePathListProperties gateWayWhitePathListProperties;
    private final StringRedisTemplate stringRedisTemplate;

    /**
     * 根据token去redis拿用户信息
     * value: hash
     */
    public static final String LOGIN_USERINFO_KEY = "short-link:login:user_info:";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().toString();
        String token = request.getHeaders().getFirst("token");
        //token = "d3395b7e561f4d9683c597e9fca311fa";
        // 白名单
        if (gateWayWhitePathListProperties.getWhitePathList().contains(path)) {
            return chain.filter(exchange);
        }
        Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(LOGIN_USERINFO_KEY + token);
        // 未登录
        if (userMap.isEmpty()) {
            return endRequest(exchange);
        }
        // 已登录
        String id = (String) userMap.get("id");
        String username = (String) userMap.get("username");
        String realName = (String) userMap.get("realName");
        ServerHttpRequest newRequest = exchange.getRequest().mutate()
                .header("id", id)
                .header("username", username)
                .header("realName", realName)
                .build();
        return chain.filter(exchange.mutate().request(newRequest).build());
    }

    private Mono<Void> endRequest(ServerWebExchange exchange) {
        GatewayErrorResult gatewayErrorResult = GatewayErrorResult.builder()
                .message("please login")
                .status(HttpStatus.FORBIDDEN.value())
                .build();
        // 4.拦截
        // 4.1.禁止访问，设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        // 将响应对象写入响应体
        return exchange.getResponse().writeWith(Mono.just(gatewayErrorResult)
                .map(object -> exchange.getResponse().bufferFactory().wrap(JSON.toJSONString(object).getBytes())));
    }
}
